package com.sl.plugin.step.ass;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sl.core.engine.meta.impl.AbstractProcessCompDescriptor;
import com.sl.core.engine.scripts.GroovyCondition;
import com.sl.core.engine.scripts.GroovyRule;
import com.sl.core.engine.scripts.RelationalOperatorEnum;
import com.sl.core.engine.step.ProcessCompService;
import com.sl.core.engine.step.impl.AbstractProcessComp;
import lombok.SneakyThrows;
import org.apache.commons.compress.utils.Lists;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.StringTemplateResourceLoader;
import org.noear.snack.ONode;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 */
//@Compensation(listener = NormalRowListener.class, type = CompensationType.SERVICE_COMPENSATION)
public class AssertComp extends AbstractProcessComp<Map<String, Object>, Map<String, Object>> implements ProcessCompService {

    public AssertComp(AbstractProcessCompDescriptor abstractProcessCompDescriptor) {
        super(abstractProcessCompDescriptor);
    }


    @SneakyThrows
    @Override
    public Map<String, Object> input(Map<String, Object> param) {


        String templateStr = meta.getStrAttr("output.templateStr");

        List<Map<String, Object>> conditionData = meta.getListMapAttr("output.conditionData");

        List<GroovyRule> s = buildScripts(conditionData, param);
        boolean evaluate = new GroovyCondition(s).evaluate(param, this.getLogChannel());

        if (BooleanUtil.isTrue(evaluate)) {
            StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
            Configuration cfg = Configuration.defaultConfiguration();
            cfg.setPlaceholderStart("${");
            cfg.setPlaceholderEnd("}");
//            cfg.setStatementStart("<!--:");
//            cfg.setsta
            cfg.build();
            GroupTemplate groupTemplate = new GroupTemplate(resourceLoader, cfg);
            Template template = groupTemplate.getTemplate(templateStr);
            template.binding(param);
            String message = template.render();
            Assert.isFalse(evaluate, message);
        }

        return param;
    }

    public static List<GroovyRule> buildScripts(List<Map<String, Object>> conditionData, Map<String, Object> param) {

        if (CollUtil.isEmpty(conditionData)) {
            return Collections.emptyList();
        }
        ONode oNode = null;
        if (ObjectUtil.isNotNull(param)) {
            oNode = ONode.loadObj(param);
        }


        List<GroovyRule> groovyRuleList = Lists.newArrayList();
        for (Map<String, Object> conditionDatum : conditionData) {

            String logicalOperator = MapUtil.getStr(conditionDatum, "logicalOperator");
            String leftBracket = MapUtil.getStr(conditionDatum, "leftBracket");
            String fieldCode = MapUtil.getStr(conditionDatum, "fieldCode");
            String relationalOperator = MapUtil.getStr(conditionDatum, "relationalOperator");
            String rightValue = MapUtil.getStr(conditionDatum, "rightValue");
            Boolean rightValueConstantFlag = MapUtil.getBool(conditionDatum, "rightValueConstantFlag");
            String rightBracket = MapUtil.getStr(conditionDatum, "rightBracket");
            Object value = rightValue;

            GroovyRule groovyRule = new GroovyRule();
            if (BooleanUtil.isFalse(rightValueConstantFlag) && StrUtil.isNotBlank(rightValue) && ObjectUtil.isNotNull(oNode)) {
                value = oNode.select(rightValue).toObject();
                groovyRule.setRightValueName(rightValue);

            }
            groovyRule.setFunction(RelationalOperatorEnum.ofCode(relationalOperator).getId());
            groovyRule.setLeftValueName(fieldCode);
            groovyRule.setRightValue(value);
            groovyRule.setLeftSymbol(leftBracket);
            groovyRule.setRightSymbol(rightBracket);
            groovyRule.setRelation(logicalOperator);
            groovyRuleList.add(groovyRule);
        }
        return groovyRuleList;
    }

}
